package framework.manager;

import haxe.ds.HashMap;
import framework.core.Singleton;
import haxe.ds.StringMap;


typedef FactoryCreateDelegate = Array<Dynamic>->Dynamic;
typedef MapFactoryItem = HashMap<String, FactoryCreateDelegate>;
typedef MapRegisterFactoryItem = HashMap<String, MapFactoryItem>;

class FactoryManager extends Singleton{

	public var instance:FactoryManager = new FactoryManager();

	private var _isInitialise:Bool;
	private var _registerFactoryItems:MapRegisterFactoryItem;

    private function new() {
		super();
		_registerFactoryItems = new MapRegisterFactoryItem();
    }

	private function _genericFactory<T>(clazz:T):FactoryCreateDelegate{
		return function(args:Array<Dynamic>){
			return Type.createInstance(clazz, []);
		}
	}

	public function registerFactory<T>(type:String):Void{
		var category = Type.getClassName(T);
		var delegate = this._genericFactory(Type.getClass(T));
		this._register(category, type, delegate);
	}

	private function _register(category:String, type:String, delegate:FactoryCreateDelegate):Void{
		var mapFactoryItems = _registerFactoryItems.get(category);
		if(mapFactoryItems == null){
			mapFactoryItems = new MapFactoryItem();
			_registerFactoryItems.set(category, mapFactoryItems);
		}
		mapFactoryItems.set(type, delegate);
	}

	public function unregisterFactory(category:String, type:String):Void{
		var mapFactoryItems = _registerFactoryItems.get(category);
		if(mapFactoryItems != null){
			mapFactoryItems.remove(type);
		}
	}

	public function isFactoryExist(category:String, type:String):Bool {
		var mapFactoryItems = _registerFactoryItems.get(category);
		if(mapFactoryItems == null){
			return false;
		}

		return mapFactoryItems.exists(type);
	}
}
